﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Qing.Lang;

namespace Qing.Std {

    class ToJson : Native {
        public override string Name { get; set; } = "转Json";
        public override string Desc { get; set; } = "参数1-任意，返回字符串；将参数1转换为Json字符串";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count > 0) {
                return new Expr(TP.Str, toJson(args[0]));
            }
            return Expr.Err("转Json函数参数不足");
        }

        public static string toJson(Expr e) {
            switch (e.Tp) {
                case TP.Bool:
                    return Convert.ToString(e.Bool()).ToLower();

                case TP.Int:
                    return Convert.ToString(e.Int());

                case TP.Float:
                    return Convert.ToString(e.Float());

                case TP.Rune:
                    return "\"" + (Parser.Char2tranfer(e.Char()) ?? e.Char().ToString()) + "\"";

                case TP.Str:
                    return "\"" + Parser.FormStr(e.Str()) + "\"";

                case TP.Arr:
                    string arrStr = "[";
                    foreach(var item in e.List!) {
                        arrStr += toJson(item) + ", ";
                    }
                    if(e.List!.Count > 0) {
                        arrStr = arrStr[0..(arrStr.Length-2)];
                    }
                    arrStr += "]";
                    return arrStr;

                case TP.Obj:
                    string objStr = "{";
                    foreach(var item in e.Ctx().Map) {
                        objStr += "\"" + item.Key[1..] + "\": " + toJson(item.Value) + ", ";
                    }
                    if (e.Ctx().Map.Count > 0) { 
                        objStr = objStr[0..(objStr.Length-2)];
                    }
                    objStr += "}";
                    return objStr;

            }

            return "undefined";
        }

    }



    class ParseJson : Native {
        public override string Name { get; set; } = "解析Json";
        public override string Desc { get; set; } = "参数1-字符串，返回任意；将参数1字符串解析为对应的数据";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Str) {
                try {
                    return parseJson(args[0].Str());
                }catch(Exception e) {
                    return Expr.Err("解析Json函数出错，" + e.Message);
                }
                
            }
            return Expr.Err("解析Json函数参数错误");
        }

        public static Expr parseJson(string str) {
            string s = str.Trim();
            if (s[0] == '"') {
                return new Expr(TP.Str, s[1..(s.Length-1)]);
            }
            int dot = Parser.IsNumberStr(s);
            if (dot == 0) {
                return new Expr(TP.Int, Convert.ToInt32(s));
            } else if (dot == 1) {
                return new Expr(TP.Float, Convert.ToDecimal(s));
            }

            Expr ret = new Expr();

            if (str[0] == '[') {
                ret.Tp = TP.Arr;
                ret.List = new List<Expr>();
                string[] ss = str[1..(str.Length-1)].Split(',');
                foreach(var item in ss) {
                    ret.List.Add(parseJson(item));
                }
                return ret;
            }

            if (str[0] == '{') {
                ret.Tp = TP.Obj;
                ret.Val = new Obj();
                string[] ss = str[1..(str.Length-1)].Split(',');
                if(ss.Length == 1 && ss[0]=="") {
                    return ret;
                }
                foreach(var item in ss) {
                    string[] kv = item.Split(':');
                    if(kv.Length != 2) {
                        throw new Exception("对象类型的Json字符串格式错误");
                    }
                    var k = kv[0].Trim();
                    k = "#" + k[1..(k.Length-1)].Trim();
                    var v = kv[1].Trim();
                    if (k[0] == '"') {
                        k = k[1..(k.Length-1)];
                    }
                    ret.Ctx().PutNow(k, parseJson(v));
                }
                return ret;
            }

            return new Expr();
        }

    }


}
